/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package Games;

/**
 *
 * @author Brandon
 */
public class TicTacToeAI extends Thread {
    
    public static final int OTHER           = 0;
    public static final int YOU             = 1;
    public static final int EMPTY           = 2;

    public static final int OTHER_WIN       = 0;
    public static final int DRAW            = 1;
    public static final int UNCLEAR         = 2;
    public static final int YOU_WIN         = 3;
    private static int[][] board;
    
    public static Best chooseMove(int player, int[][] board) {
        TicTacToeAI.board = copyBoard(board);
        return ai(player,TicTacToeAI.board);
    }
    
    private static int[][] copyBoard(int[][] board) {
        int[][] newBoard = new int[board.length][board[0].length];
        for (int n = 0; n < newBoard.length; n++) {
                System.arraycopy(board[n], 0, newBoard[n], 0, board[n].length);
        }
        return newBoard;
    }
    
    public static Best ai(int player, int[][] board) {
        int opp;              // The other side
        int simpleEval;       // Result of an immediate evaluation
        Best reply;           // Opponent's best reply
        int value;
        int bestRow = 0;
        int bestCol = 0;
        if( ( simpleEval = positionValue() ) != UNCLEAR ) {
            return new Best(simpleEval);
        }

        if(player == YOU ) {
            opp = OTHER; value = OTHER_WIN;
        } else {
            opp = YOU; value = YOU_WIN;
        }

        for( int col = 0; col < 3; col++ ) {
            for( int row = 0; row < 3; row++ ) {
                if(squareIsEmpty(col, row)){
                    place(col, row, player);
                    reply = ai(opp,board);
                    place(col, row, EMPTY );

                    // Update if side gets better position
                    if(( player == YOU && reply.val > value)|| (player == OTHER && reply.val < value )){
                       value = reply.val;
                       bestCol = col;
                       bestRow = row;
                    }
                }
            }
        }
        return new Best(value, bestCol, bestRow);
    }
    
    private static void setBoard(int[][] board) {
        TicTacToeAI.board = board;
    }
    
    private static boolean squareIsEmpty( int row, int column ) {
        return board[row][column] == EMPTY;
    }
    
    // Play a move, possibly clearing a square
    private static void place( int row, int column, int piece ) {
        board[row][column] = piece;
    }
    
    public static int positionValue() {
        if(isAWin(OTHER)){
            return OTHER_WIN;
        }else if(isAWin(YOU)){
            return YOU_WIN;
        }else if(boardIsFull()){
            return DRAW;
        }else{
            return UNCLEAR;
        }
    }
    
    private static boolean boardIsFull() {
        for(int row = 0; row < board.length; row++){
            for(int col = 0; col < board[row].length; col++){
                if(board[row][col] == EMPTY){
                    return false;
                }
            }
        }
        return true;
    }

    // Returns whether 'side' has won in this position
    public static boolean isAWin(int side) {
        for(int row = 0; row < board.length; row++){
            if(board[row][0] == side){
                if(board[row][1] == side){
                    if(board[row][2] == side){
                        return true;
                    }
                }
            }
        }
        for(int col = 0; col < board.length; col++){
            if(board[0][col] == side){
                if(board[1][col] == side){
                    if(board[2][col] == side){
                        return true;
                    }
                }
            }
        }
        if((board[0][0] == side) && (board[1][1] == side) && (board[2][2] == side))
            return true;
        else if((board[2][0] == side) && (board[1][1] == side) && (board[0][2] == side))
            return true;
        else
            return false;
    }
}
